package de.fhhannover.inform.itteam.snmpnetviz;

import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import de.fhhannover.inform.itteam.snmpnetviz.gui.LoadingWindow;

public class SnmpSwitchCallable implements Callable<HostEntry> {
	private HostEntry mSwitchEntry;
	private String[][] mSwitchConnections;
	private IpToMac mIpToMacTable;
	private LoadingWindow mLoadingWindow;
	
	public SnmpSwitchCallable(HostEntry switchEntry,String[][] switches,IpToMac ipToMacTable,LoadingWindow loadingWindow) {
		mSwitchEntry = switchEntry;
		mSwitchConnections = switches;
		mIpToMacTable = ipToMacTable;
		mLoadingWindow = loadingWindow;
	}

	public HostEntry call() {
		IpMacInterfaceTable table = new IpMacInterfaceTable(mSwitchEntry,mIpToMacTable,mSwitchConnections);
		mLoadingWindow.setStatusText("Read child hosts and switches from switch "+mSwitchEntry.getIpAddress()+"...");
		
		if (mSwitchEntry!=null) {			
			ExecutorService executor = new snmpExecutor();
			CopyOnWriteArrayList<Future<HostEntry>> futures = new CopyOnWriteArrayList<Future<HostEntry>>();
			
			// iterate trough each child switch and get its MAC
			for (int i=0;i<mSwitchConnections.length;i++) {				
				if (mSwitchConnections[i][0].equals(mSwitchEntry.getIpAddress())) {
					futures.add(executor.submit(new SnmpSwitchCallable(table.getHostForIp(mSwitchConnections[i][1]),mSwitchConnections,mIpToMacTable,mLoadingWindow)));
				}
				if (mSwitchEntry.getParent()!=null) {
					HostEntry hostForIp = table.getHostForIp(mSwitchEntry.getParent().getIpAddress());
					if (hostForIp!=null) mSwitchEntry.addChildren(hostForIp);
				}
			}
			
			Iterator<Future<HostEntry>> fIT = futures.iterator();
			while (fIT.hasNext()) {
				try {
					Future<HostEntry> next = fIT.next();
					HostEntry children = next.get();
					mSwitchEntry.addChildren(children);
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (ExecutionException e) {
					e.printStackTrace();
				}
			}
			executor.shutdown();
			

			// add all HostEntrys from table if they have a different port than the switches
			Iterator<HostEntry> it = table.getPortEntrys();
			
			while(it.hasNext()) {
				HostEntry current = it.next();
				HostEntry switchForPort = mSwitchEntry.getSwitchForPort(current.getPort());
				if(switchForPort==null) {
					mSwitchEntry.addChildren(current);
				}
			}
		}

		return mSwitchEntry;
	}

}
